package ${packageName}.app.configuration;

import android.app.Application;
import android.content.Context;

import com.google.gson.GsonBuilder;

import ${packageName}.mvp.model.api.ApiURLPath;
import ${packageName}.mvp.model.api.interceptor.AuthTokenInterceptor;

import com.jpxx.base.http.converter.APIResponseDataConverter;
import com.jpxx.base.http.converter.RequestDataEncryptCallBack;
import com.jpxx.base.http.converter.ResponseDataDecryptCallBack;
import com.jpxx.base.http.proxy.SafeProxySelector;
import com.jpxx.base.ui.mvp.base.delegate.AppLifecycles;
import com.jpxx.base.ui.mvp.di.module.GlobalConfigModule;
import com.jpxx.base.http.interceptor.RequestInterceptor;
import com.jpxx.base.ui.mvp.integration.ConfigModule;

import com.readystatesoftware.chuck.ChuckInterceptor;

import java.util.List;
import java.util.concurrent.TimeUnit;

import ${packageName}.BuildConfig;

import androidx.fragment.app.FragmentManager;

/**
 * ================================================
 * App 的全局配置信息在此配置, 需要将此实现类声明到 AndroidManifest 中
 * ConfigModule 的实现类可以有无数多个, 在 Application 中只是注册回调, 并不会影响性能 (多个 ConfigModule 在多 Module 环境下尤为受用)
 * ConfigModule 接口的实现类对象是通过反射生成的, 这里会有些性能损耗
 *
 * @see com.jpxx.base.ui.mvp.base.delegate.AppComponentDelegate
 * @see com.jpxx.base.ui.mvp.integration.ManifestParser
 * ================================================
 */
public final class GlobalConfiguration implements ConfigModule {

    @Override
    public void applyOptions(Context context, GlobalConfigModule.Builder builder) {
        if (!BuildConfig.DEV_MODE) { //Production 时, 让框架不再打印 Http 请求和响应的信息
            builder.printHttpLogLevel(RequestInterceptor.Level.NONE);
        }

        // 切换production和staging环境域名
        builder.baseurl(ApiURLPath.getCustomApiBaseUrl())

                //可根据当前项目的情况以及环境为框架某些部件提供自定义的缓存策略, 具有强大的扩展性
//                .cacheFactory(new Cache.Factory() {
//                    @NonNull
//                    @Override
//                    public Cache build(CacheType type) {
//                        switch (type.getCacheTypeId()){
//                            case CacheType.EXTRAS_TYPE_ID:
//                                return new IntelligentCache(500);
//                            case CacheType.CACHE_SERVICE_CACHE_TYPE_ID:
//                                return new Cache(type.calculateCacheSize(context));//自定义 Cache
//                            default:
//                                return new LruCache(200);
//                        }
//                    }
//                })

                //可以自定义一个单例的线程池供全局使用
//                .executorService(Executors.newCachedThreadPool())

                //这里提供一个全局处理 Http 请求和响应结果的处理类, 可以比客户端提前一步拿到服务器返回的结果, 可以做一些操作, 比如 Token 超时后, 重新获取 Token
                .globalHttpHandler(new GlobalHttpHandlerImpl(context))
                .gsonConfiguration((context1, gsonBuilder) -> {//这里可以自己自定义配置 Gson 的参数
                    gsonBuilder
                            .serializeNulls()//支持序列化值为 null 的参数
                            .enableComplexMapKeySerialization();//支持将序列化 key 为 Object 的 Map, 默认只能序列化 key 为 String 的 Map
                })
                .retrofitConfiguration((context1, retrofitBuilder) -> {
                    //这里可以自己自定义配置 Retrofit 的参数, 甚至您可以替换框架配置好的 OkHttpClient 对象
                    // (但是不建议这样做, 这样做您将损失框架提供的很多功能)

                    //需要 请求加密，响应解密时，传入 requestDataEncryptCallBack, responseDataDecryptCallBack
                    RequestDataEncryptCallBack requestDataEncryptCallBack = new RequestDataEncryptCallBackImpl(); // 请求加密
                    ResponseDataDecryptCallBack responseDataDecryptCallBack = new ResponseDataDecryptCallBackImpl(); //响应解密

                    retrofitBuilder.addConverterFactory(APIResponseDataConverter.create(
                            new GsonBuilder().serializeNulls().create(),
                            requestDataEncryptCallBack,
                            responseDataDecryptCallBack)
                    );
                })
                .addInterceptor(new AuthTokenInterceptor()) //添加自定义Auth Token Interceptor
                .okhttpConfiguration((context1, okhttpBuilder) -> {//这里可以自己自定义配置 Okhttp 的参数
                    // HTTPS 详情请百度
                    // HttpsUtils.SSLParams sslParams; // https 自签名证书信息
                    // okhttpBuilder.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
                    okhttpBuilder.writeTimeout(10, TimeUnit.SECONDS);
                    okhttpBuilder.connectTimeout(10, TimeUnit.SECONDS);
                    okhttpBuilder.readTimeout(10, TimeUnit.SECONDS);

                    // 不使用代理
                    okhttpBuilder.proxySelector(new SafeProxySelector());

                    // 通知栏 log 日志
                    if(BuildConfig.DEV_MODE){
                        okhttpBuilder.addInterceptor(new ChuckInterceptor(context1));
                    }
                })
                .rxCacheConfiguration((context1, rxCacheBuilder) -> {//这里可以自己自定义配置 RxCache 的参数
                    rxCacheBuilder.useExpiredDataIfLoaderNotAvailable(true);
                    //想自定义 RxCache 的缓存文件夹或者解析方式, 如改成 FastJson, 请 return rxCacheBuilder.persistence(cacheDirectory, new FastJsonSpeaker());
                    //否则请 return null;
                    return null;
                });
    }

    @Override
    public void injectAppLifecycle(Context context, List<AppLifecycles> lifecycles) {
        //AppLifecycles 中的所有方法都会在基类 Application 的对应生命周期中被调用, 所以在对应的方法中可以扩展一些自己需要的逻辑
        //可以根据不同的逻辑添加多个实现类
        lifecycles.add(new AppLifecyclesImpl());
    }

    @Override
    public void injectActivityLifecycle(Context context, List<Application.ActivityLifecycleCallbacks> lifecycles) {
        //ActivityLifecycleCallbacks 中的所有方法都会在 Activity (包括三方库) 的对应生命周期中被调用, 所以在对应的方法中可以扩展一些自己需要的逻辑
        //可以根据不同的逻辑添加多个实现类
        lifecycles.add(new ActivityLifecycleCallbacksImpl());
    }

    @Override
    public void injectFragmentLifecycle(Context context, List<FragmentManager.FragmentLifecycleCallbacks> lifecycles) {
        //FragmentLifecycleCallbacks 中的所有方法都会在 Fragment (包括三方库) 的对应生命周期中被调用, 所以在对应的方法中可以扩展一些自己需要的逻辑
        //可以根据不同的逻辑添加多个实现类
        lifecycles.add(new FragmentLifecycleCallbacksImpl());
    }
}
